#ifndef ARCHIVOINDICE_H_
#define ARCHIVOINDICE_H_
#include "Tipos.h"
#include "NodoBase.h"
#include "Nodo.h"
#include "Hoja.h"
//#include <iostream>
//#include <fstream>

using namespace std;
template <class CClave >
class CArchivoIndice
{
	fstream 			m_archivo;
	ifstream 			m_lectura;
	ofstream 			m_escritura;
	string				m_nombre;	
public:
	CArchivoIndice(string nombre);
	CArchivoIndice(){}
	~CArchivoIndice();
	void read(CNodo<CClave> & buffer,TIPO_DATO nroBloque);
	void read(CHoja<CClave> & buffer,TIPO_DATO tamanio);	
	/*el metodo lee el bloque del archivo de indices indicando si es nodo u hoja  dependiendo del nivel*/
	/* true => nodo
		false => hoja*/
	bool leerBloque(TIPO_DATO,char bufferAux[TAMANIO_NODO]);
//	void seekg(int posicion,IOS::HACER);
	TIPO_DATO getTamanio();

	TIPO_DATO cantBloques();
	TIPO_DATO escribir(MapNodo rama);
	bool is_open();
	void cerrar();
	
	void write(CNodo<CClave> *buffer);
	void write(CHoja<CClave> *buffer);
	
};
/*-----------------------------------------------------------*/
template <class CClave >
CArchivoIndice<CClave >::CArchivoIndice(string nombre)
{
	m_archivo.open(nombre.c_str(),ios::in | ios::out | ios::binary | ios::trunc);

	if(!m_archivo.is_open())
		cout<<"El archivo indice no se pudo crear."<<endl;
	m_nombre = nombre;
}
/*-----------------------------------------------------------*/
template <class CClave >
bool CArchivoIndice<CClave >::is_open()
{
	return m_archivo.is_open();
}
/*-----------------------------------------------------------*/
template <class CClave >
void CArchivoIndice<CClave >::cerrar()
{
	m_archivo.close();
}
/*-----------------------------------------------------------*/
template <class CClave >
void CArchivoIndice<CClave >::write(CNodo<CClave> *buffer)
{
	string dato="";
	int borrarme;
	char aux[TAMANIO_NODO+1]={};
	TIPO_DATO nroblock;
	if(!m_archivo.is_open())
		cout<<"El archivo indice no esta abierto y se desea escribir."<<endl;
//	if(buffer->getCantRegistros()!=0)
	{
		nroblock = buffer->getNroBloque();
	//	if(nroblock==14)
	//		cout<<"inserta el bloque 14"<<endl;	
		dato = buffer->desTransformar();
	//if(m_archivo.bad())	
	//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;
		m_archivo.seekp(nroblock*TAMANIO_NODO,ios::beg);
		strncpy(aux,dato.c_str(),TAMANIO_NODO);
		borrarme = (int)dato.length();
	//if(m_archivo.bad())	
	//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;
		//cout<<"ESCRITURA DEL NODO"<<aux<<endl;
	//	cout<<"MUESTRO LO QUE VOY A ESCRIBIR !!!!!!!!!!!!!!!!!"<<endl;
	//	buffer->mostrar();
		m_archivo.write(aux,TAMANIO_NODO);
	}
//	if(m_archivo.bad())	
//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;

}
/*-----------------------------------------------------------*/
template <class CClave >
void CArchivoIndice<CClave >::write(CHoja<CClave> *buffer)
{
	int borrame=0;
	string dato="";	
	char aux[TAMANIO_NODO+1]={};
//	char *aux=NULL;
//	aux=new char[TAMANIO_NODO+1];
	
	TIPO_DATO nroblock;
	//m_archivo.flush();
	if(!m_archivo.is_open())
		cout<<"El archivo indice no esta abierto y se desea escribir."<<endl;
//	buffer->mostrar();
//	if(buffer->getCantRegistros()!=0)
	{
		nroblock = buffer->getNroBloque();
	//	if(nroblock==2)
	//		cout<<"inserta el bloque 14"<<endl;

		dato = buffer->desTransformar();
		borrame = (int)dato.length();

		strncpy(aux,dato.c_str(),TAMANIO_NODO);
		this->m_archivo.seekp(nroblock*TAMANIO_NODO,ios::beg);
	//	cout<<"MUESTRO LO QUE VOY A ESCRIBIR !!!!!!!!!!!!!!!!!"<<endl;
	//	buffer->mostrar();	
		this->m_archivo.write(aux,TAMANIO_NODO);
	}
//	if(m_archivo.bad())	
//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;

//	this->m_escritura.write(reinterpret_cast<char *>(aux),TAMANIO_NODO);
	//this->m_archivo.write("HOLA",4);
	//delete[] aux;
}
/*-----------------------------------------------------------*/
template <class CClave >
TIPO_DATO CArchivoIndice<CClave >::getTamanio()
{
	TIPO_DATO tamanio=0;
	if(!m_archivo.is_open())
		cout<<"El archivo indice no esta abierto y se desea saber el tamanio."<<endl;
//	if(m_archivo.bad())	
//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;
	
	this->m_archivo.seekg(0, ios::end);	//se posiciona al final del archivo
	tamanio = this->m_archivo.tellg(); //indica en que pos del arch se encuentra (en byte)
	this->m_archivo.seekg(0, ios::beg);	//se posiciona al inicio del archivo	
	if(tamanio==ULONG_MAX)
	{
		this->m_archivo.seekp(0, ios::end);	//se posiciona al final del archivo
		tamanio = this->m_archivo.tellp(); //indica en que pos del arch se encuentra (en byte)
		this->m_archivo.seekp(0,ios::beg);	//se posiciona al inicio del archivo	

	}
	return tamanio;
}
/*-----------------------------------------------------------*/
template <class CClave >
CArchivoIndice<CClave >::~CArchivoIndice()
{
	if(m_archivo.is_open())
		m_archivo.close();	
}
/*-----------------------------------------------------------*/
template <class CClave >
void CArchivoIndice<CClave >::read(CNodo<CClave> & buffer,TIPO_DATO nroBloque)
{
	char bufferAux[TAMANIO_NODO+1]={};
	if(!m_archivo.is_open())
	{
		cout<<"el archivo que se desea leer no esta abierto!!!"<<endl;
		return;
	}
	/**TODO tendria que tener un metodo que cargue en la estructura convirtiendo
	 *  la cadena de char en la estructura*/
	
	m_archivo.seekg(TAMANIO_NODO*nroBloque, ios::beg);
	m_archivo.read(bufferAux,TAMANIO_NODO);	
	//cout<<"LECTURA DEL NODO"<<bufferAux<<endl;
//	if(m_archivo.bad())	
//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;
	buffer.transformar((string)bufferAux);
	buffer.setNroBloque(nroBloque);
//	cout<<"<<<<<<<<<<<<<<<<<<<<MUESTRO LO QUE VOY A LEER >>>>>>>>>>>"<<endl;
//	buffer.mostrar();
	
}
/*-----------------------------------------------------------*/
template <class CClave >
void CArchivoIndice<CClave >::read(CHoja<CClave> & buffer,TIPO_DATO nroBloque)
{
	char bufferAux[TAMANIO_NODO+1]={};
	if(!m_archivo.is_open())
	{
		cout<<"el archivo que se desea leer no esta abierto!!!"<<endl;
		return;
	}
	/**TODO tendria que tener un metodo que cargue en la estructura convirtiendo
	 *  la cadena de char en la estructura*/
	m_archivo.seekg(TAMANIO_NODO*nroBloque, ios::beg);
	m_archivo.read(bufferAux,TAMANIO_NODO);
	//cout<<"LECTURA DE la HOJA"<<bufferAux<<endl;		
//	if(m_archivo.bad())	
//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;

	buffer.transformar(bufferAux);
	buffer.setNroBloque(nroBloque);
//	cout<<"<<<<<<<<<<<<<<<<<<<<MUESTRO LO QUE VOY A LEER >>>>>>>>>>>"<<endl;
//	buffer.mostrar();

//	m_archivo.gcount();//sizeof(TRegistro)
	//buffer.transformar(bufferAux);
}
/*-----------------------------------------------------------*/
template <class CClave >
TIPO_DATO  CArchivoIndice<CClave >::cantBloques()
{	
	return getTamanio()/TAMANIO_NODO;//nos devuelve la cantidad de bloques
}
template <class CClave >
bool CArchivoIndice<CClave >::leerBloque(TIPO_DATO nroBloque ,char bufferAux[TAMANIO_NODO])
{
	if(!m_archivo.is_open())
		cout<<"el archivo que se desea leer no esta abierto!!!"<<endl;
	/**TODO tendria que tener un metodo que cargue en la estructura convirtiendo
	 *  la cadena de char en la estructura*/
	m_archivo.seekg(TAMANIO_NODO*nroBloque, ios::beg);
	m_archivo.read(bufferAux,TAMANIO_NODO);
	//cout<<"LECTURA DE la HOJA"<<bufferAux<<endl;		
//	if(m_archivo.bad())	
//		cout<<"el archivo es malo JHOOOOOOOOOONNNNNNNNNN�����������������############!!!"<<endl;
	//el numero 1 corresponde a nivel 0 una hoja
	if(bufferAux[1]==1)
		return false;
	return true;
}

#endif /*ARCHIVOINDICE_H_*/

